from typing import Dict, List, Optional, Union, BinaryIO, Any, Type, Callable
import importlib
import logging
from datetime import datetime, timedelta

from .base_client import (
    BaseCloudClient, LoginCredentials, PersistentLoginInfo, 
    AccountInfo, FileInfo, TrashItem
)
# from .persistence import PersistenceManager, get_default_persistence_manager


class CloudFileSystem:
    """云盘文件系统管理器，负责管理多个云盘实例和统一接口实现"""
    
    def __init__(self, 
                 on_persistent_info_updated: Optional[Callable[[str, str, PersistentLoginInfo], None]] = None,
                 enable_cache: bool = True, cache_config: Optional[Dict[str, Any]] = None):
        """
        初始化云盘文件系统管理器
        
        Args:
            persistence_manager: 持久化管理器，如果为None则使用默认管理器
            on_persistent_info_updated: 持久化信息更新回调函数，参数为(provider, username, persistent_info)
            enable_cache: 是否启用缓存功能
            cache_config: 缓存配置参数
        """
        self.clients: Dict[str, BaseCloudClient] = {}  # provider -> client instance
        self.client_classes: Dict[str, Type[BaseCloudClient]] = {}  # provider -> client class
        self.logger = logging.getLogger(__name__)
        
        # 持久化管理器
        # self.persistence_manager = persistence_manager or get_default_persistence_manager()
        self.on_persistent_info_updated = on_persistent_info_updated
        
        # 缓存配置
        self.enable_cache = enable_cache
        self.cache_config = cache_config or {}
        
        # 注册内置的云盘提供商
        self._register_builtin_providers()
    
    def _register_builtin_providers(self):
        """注册内置的云盘提供商"""
        try:
            # 注册本地存储
            from .local_storage.local_client import LocalStorageClient
            self.register_provider("local", LocalStorageClient)
        except ImportError:
            self.logger.warning("Local storage client not found")
        
        try:
            # 注册天翼云盘PC版
            from .tianyi_pc.tianyi_pc_client import TianyiPCClient
            self.register_provider("tianyi_pc", TianyiPCClient)
        except ImportError:
            self.logger.warning("Tianyi PC client not found")
    
    def register_provider(self, provider: str, client_class: Type[BaseCloudClient]):
        """注册云盘提供商"""
        self.client_classes[provider] = client_class
        self.logger.info(f"Registered provider: {provider}")
    
    def get_available_providers(self) -> List[str]:
        """获取可用的云盘提供商列表"""
        return list(self.client_classes.keys())
    
    def create_client(self, provider: str, **kwargs) -> BaseCloudClient:
        """创建云盘客户端实例"""
        if provider not in self.client_classes:
            raise ValueError(f"Unknown provider: {provider}")
        
        # 为TianyiPCClient添加缓存参数
        if provider == "tianyi_pc" and self.enable_cache:
            # 设置默认缓存配置
            cache_params = {
                'enable_path_cache': True,
                'path_cache_size': self.cache_config.get('path_cache_size', 10000),
                'folder_cache_size': self.cache_config.get('folder_cache_size', 1000),
                'folder_cache_ttl': self.cache_config.get('folder_cache_ttl', 300)
            }
            kwargs.update(cache_params)
        elif provider == "tianyi_pc" and not self.enable_cache:
            # 禁用缓存
            kwargs.update({
                'enable_path_cache': False,
                'path_cache_size': 0,
                'folder_cache_size': 0,
                'folder_cache_ttl': 0
            })
        
        return self.client_classes[provider](provider, **kwargs)
    
    def add_account(self, provider: str, credentials: LoginCredentials, 
                   save_persistent: bool = True) -> PersistentLoginInfo:
        """
        添加云盘账号（首次登录）
        
        Args:
            provider: 云盘提供商
            credentials: 登录凭据
            save_persistent: 是否保存持久化信息
        """
        account_key = f"{provider}_{credentials.username}"
        
        # 创建客户端并登录
        client = self.create_client(provider)
        
        try:
            persistent_info = client.login(credentials)
            self.clients[account_key] = client
            
            # 保存持久化信息
            # if save_persistent:
                # success = self.persistence_manager.save_persistent_info(
                #     provider, credentials.username, persistent_info
                # )
                # if not success:
                #     self.logger.warning(f"Failed to save persistent info for {account_key}")
                
                # 触发回调
                # if self.on_persistent_info_updated:
                #     self.on_persistent_info_updated(provider, credentials.username, persistent_info)
            
            self.logger.info(f"Successfully added account: {account_key}")
            return persistent_info
            
        except Exception as e:
            self.logger.error(f"Failed to add account {account_key}: {e}")
            raise
    
    def load_account(self, provider: str, username: str, 
                    credentials: LoginCredentials, 
                    persistent_info: Optional[PersistentLoginInfo] = None,
                    auto_load_persistent: bool = True,
                    save_persistent: bool = True) -> bool:
        """
        加载云盘账号（支持持久化登录）
        先尝试使用持久化信息登录，失败则使用凭据重新登录
        
        Args:
            provider: 云盘提供商
            username: 用户名
            credentials: 登录凭据
            persistent_info: 持久化信息（可选）
            auto_load_persistent: 是否自动从持久化管理器加载信息
            save_persistent: 重新登录时是否保存新的持久化信息
        """
        account_key = f"{provider}_{username}"
        
        # 创建客户端实例
        client = self.create_client(provider)
        
        # 如果没有提供持久化信息且允许自动加载，则从持久化管理器加载
        # if persistent_info is None and auto_load_persistent:
        #     persistent_info = self.persistence_manager.load_persistent_info(provider, username)
        

        # 使用凭据重新登录
        try:
            new_persistent_info = client.login(credentials)
            self.clients[account_key] = client
            self.logger.info(f"Successfully loaded account with fresh login: {account_key}")
            
            # 保存新的持久化信息
            # if save_persistent:
                # success = self.persistence_manager.save_persistent_info(
                #     provider, username, new_persistent_info
                # )
                # if not success:
                #     self.logger.warning(f"Failed to save new persistent info for {account_key}")
                
                # # 触发回调
                # if self.on_persistent_info_updated:
                #     self.on_persistent_info_updated(provider, username, new_persistent_info)
            
            return True
            
        except Exception as e:
            self.logger.error(f"Failed to load account {account_key}: {e}")
            return False
    
    def remove_account(self, provider: str, username: str, 
                      remove_persistent: bool = True) -> bool:
        """
        移除云盘账号
        
        Args:
            provider: 云盘提供商
            username: 用户名
            remove_persistent: 是否同时删除持久化信息
        """
        account_key = f"{provider}_{username}"
        
        # 登出客户端
        if account_key in self.clients:
            client = self.clients[account_key]
            try:
                client.logout()
            except Exception as e:
                self.logger.warning(f"Logout error for {account_key}: {e}")
            
            del self.clients[account_key]
        
        # 删除持久化信息
        # if remove_persistent:
        #     success = self.persistence_manager.remove_persistent_info(provider, username)
        #     if not success:
        #         self.logger.warning(f"Failed to remove persistent info for {account_key}")
        
        self.logger.info(f"Removed account: {account_key}")
        return True
    
    def get_client(self, provider: str, username: str) -> Optional[BaseCloudClient]:
        """获取云盘客户端实例"""
        account_key = f"{provider}_{username}"
        return self.clients.get(account_key)
    
  
    

    

    # ==============================
    # 登录验证接口
    # ==============================
    
    def validate_login(self, provider: str, username: str) -> bool:
        """
        验证账号登录状态
        
        Args:
            provider: 云盘提供商
            username: 用户名
            
        Returns:
            bool: 验证是否通过
        """
        try:
            client = self.get_client(provider, username)
            if not client:
                return False
            
            # 调用客户端的验证方法
            return client.validate_login(provider, username)
            
        except Exception as e:
            self.logger.error(f"登录验证失败 {provider}_{username}: {e}")
            return False
    
    # ==============================
    # 统一文件操作接口
    # ==============================
    
    def _get_authenticated_client(self, provider: str, username: str) -> BaseCloudClient:
        """获取已认证的客户端，如果未认证则抛出异常"""
        client = self.get_client(provider, username)
        if not client:
            raise ValueError(f"Account not found: {provider}_{username}")
        
        if not client.is_authenticated or not client.is_login_valid():
            raise ValueError(f"Account not authenticated: {provider}_{username}")
        
        return client
    
    def _normalize_path(self, path: str) -> str:
        """标准化路径格式"""
        if not path:
            return "/"
        
        # 统一使用正斜杠
        path = path.replace('\\', '/')
        
        # 确保以/开头
        if not path.startswith('/'):
            path = '/' + path
        
        # 移除重复的斜杠
        while '//' in path:
            path = path.replace('//', '/')
        
        # 根目录特殊处理
        if path == '/':
            return path
        
        # 移除末尾的斜杠
        if path.endswith('/'):
            path = path[:-1]
        
        return path
    
    def _validate_provider_and_username(self, provider: str, username: str) -> bool:
        """验证提供商和用户名参数"""
        if not provider or not isinstance(provider, str):
            self.logger.error("提供商参数无效")
            return False
        
        if not username or not isinstance(username, str):
            self.logger.error("用户名参数无效")
            return False
        
        return True
    
    # 文件上传
    def upload_file(self, provider: str, username: str, 
                   file_stream: Union[bytes, BinaryIO], remote_path: str, **kwargs) -> bool:
        """上传文件"""
        if not self._validate_provider_and_username(provider, username):
            return False
        
        remote_path = self._normalize_path(remote_path)
        
        try:
            client = self._get_authenticated_client(provider, username)
            return client.upload_file(file_stream, remote_path, **kwargs)
        except Exception as e:
            self.logger.error(f"上传文件失败: {e}")
            return False
    
    def check_quick_upload(self, provider: str, username: str, file_md5: str) -> bool:
        """检查是否支持秒传"""
        client = self._get_authenticated_client(provider, username)
        return client.check_quick_upload(file_md5)
    
    def quick_upload(self, provider: str, username: str, 
                    file_md5: str, remote_path: str, **kwargs) -> bool:
        """秒传文件"""
        client = self._get_authenticated_client(provider, username)
        return client.quick_upload(file_md5, remote_path, **kwargs)

    
    def get_download_url(self, provider: str, username: str, 
                        remote_path: str, expires_in: int = 3600) -> str:
        """获取下载链接"""
        client = self._get_authenticated_client(provider, username)
        return client.get_download_url(remote_path, expires_in)
    
    # 文件管理
    def list_files(self, provider: str, username: str, remote_path: str = "/") -> List[FileInfo]:
        """列出目录下的文件"""
        client = self._get_authenticated_client(provider, username)
        return client.list_files(remote_path)
    
    def get_file_info(self, provider: str, username: str, remote_path: str) -> FileInfo:
        """获取文件信息"""
        client = self._get_authenticated_client(provider, username)
        return client.get_file_info(remote_path)
    
    def create_folder(self, provider: str, username: str, remote_path: str) -> bool:
        """创建文件夹"""
        client = self._get_authenticated_client(provider, username)
        return client.create_folder(remote_path)
    
    def delete_file(self, provider: str, username: str, 
                   remote_path: str, permanent: bool = False) -> bool:
        """删除文件或文件夹"""
        client = self._get_authenticated_client(provider, username)
        return client.delete_file(remote_path, permanent)
    
    def move_file(self, provider: str, username: str, src_path: str, dst_path: str) -> bool:
        """移动文件或文件夹"""
        client = self._get_authenticated_client(provider, username)
        return client.move_file(src_path, dst_path)
    
    def copy_file(self, provider: str, username: str, src_path: str, dst_path: str) -> bool:
        """复制文件或文件夹"""
        client = self._get_authenticated_client(provider, username)
        return client.copy_file(src_path, dst_path)
    
    def rename_file(self, provider: str, username: str, remote_path: str, new_name: str) -> bool:
        """重命名文件或文件夹"""
        client = self._get_authenticated_client(provider, username)
        return client.rename_file(remote_path, new_name)
    
    def file_exists(self, provider: str, username: str, remote_path: str) -> bool:
        """检查文件是否存在"""
        client = self._get_authenticated_client(provider, username)
        return client.file_exists(remote_path)
    
    # 账号信息
    def get_account_info(self, provider: str, username: str) -> Optional[AccountInfo]:
        """获取账号信息"""
        client = self._get_authenticated_client(provider, username)
        return client.get_account_info()
    
    # 回收站操作
    def list_trash(self, provider: str, username: str) -> List[TrashItem]:
        """列出回收站内容"""
        client = self._get_authenticated_client(provider, username)
        return client.list_trash()
    
    def restore_from_trash(self, provider: str, username: str, 
                          original_path: str, target_path: Optional[str] = None) -> bool:
        """从回收站恢复文件"""
        client = self._get_authenticated_client(provider, username)
        return client.restore_from_trash(original_path, target_path)
    
    def delete_from_trash(self, provider: str, username: str, original_path: str) -> bool:
        """从回收站永久删除文件"""
        client = self._get_authenticated_client(provider, username)
        return client.delete_from_trash(original_path)
    
    def empty_trash(self, provider: str, username: str) -> int:
        """清空回收站"""
        client = self._get_authenticated_client(provider, username)
        return client.empty_trash()
    
    def get_trash_item_info(self, provider: str, username: str, original_path: str) -> Optional[TrashItem]:
        """获取回收站项目信息"""
        client = self._get_authenticated_client(provider, username)
        return client.get_trash_item_info(original_path)